#include "wdtx_queue.h"

struct queueStruct
{
    List list;
    u16 head;
    u16 tail;
    bool full;
};

Queue Queue_newInstance(u8 sizeOfNode, u16 maxLength)
{
    Queue queue = (Queue)malloc(sizeof(struct queueStruct));
    queue->head = 0;
    queue->tail = 0;
    queue->full = false;
    queue->list = List_newInstance(sizeOfNode,maxLength);

    return queue;
}

void Queue_destory(Queue queue)
{
    List_destroy(queue->list);
    free(queue);
}

const void* Queue_top(Queue queue)
{
    if(!Queue_notEmpty(queue))
    {
        return NULL;
    }
    return List_get(queue->list,queue->head);
}

void* Queue_pop(Queue queue)
{
    void *value;
    if(!Queue_notEmpty(queue))
    {
        return NULL;
    }

    value = List_get(queue->list,queue->head);
    queue->head++;
    queue->head = (queue->head) % List_getMaxLength(queue->list);

    queue->full = false;
    return value;
}

void Queue_push(Queue queue, const void* value)
{
    if(queue->full)
    {
        return;
    }

    List_set(queue->list,queue->tail,value);
    queue->tail += 1;
    queue->tail = (queue->tail) % List_getMaxLength(queue->list);

    if(queue->head == queue->tail)
    {
        queue->full = true;
    }
}

bool Queue_notEmpty(Queue queue)
{
    if(queue->head == queue->tail && queue->full == false)
    {
        return false;
    }
    else
    {
        return true;
    }
}

bool Queue_notFull(Queue queue)
{
    return queue->full ? false : true;
}

u16 Queue_length(Queue queue)
{
    u8 maxLength = List_getMaxLength(queue->list);
    if(queue->full)
    {
        return maxLength;
    }
    else
    {
        if(queue->tail > queue->head)
        {
            return queue->tail - queue->head;
        }
        return (queue->tail + maxLength - queue->head) % maxLength;
    }
}
